package org.fly.filter;

import org.fly.bean.BaseUser;
import org.fly.utils.UserContext;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

import javax.servlet.*;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * Created by rongzhao.zhu on 2018/2/16.
 */
public abstract class LoginFilter implements Filter {

    private String excludeUriStr;
    /**
     * 不需要登录验证的uri
     */

    protected List<String> excludeUri;



    WebApplicationContext wac;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        excludeUriStr = filterConfig.getInitParameter("excludeUriStr");
        ServletContext context = filterConfig.getServletContext();
        wac = WebApplicationContextUtils.getWebApplicationContext(context);
        excludeUri = Arrays.asList(excludeUriStr.split(","));
    }

    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        String uri = request.getRequestURI();
        //如果是不需要登录验证的uri 则直接继续
        if(excludeUri.contains(uri)){
            filterChain.doFilter(request, response);
            return;
        }else {
            try{
                BaseUser user = getUser(request);
                try{
                    if(user != null){
                        onLogin(request,response,user);
                    }else {
                        onNoLogin(request,response);
                        return;
                    }
                }catch (Exception e){
                    onException(request,response,e);
                    return;
                }
                filterChain.doFilter(request, response);
            }finally {
                onFinal();
            }

        }


    }

    @Override
    public void destroy() {

    }
    /**
     * 将cookie 组成键值对
     * @param cookies
     * @return
     */
    protected Map<String,String> cookie2map(Cookie[] cookies){
        return Stream.of(cookies).collect(Collectors.toMap(Cookie::getName,Cookie::getValue));
    }

    /**
     * 通过cookie获取用户信息
     * @param request
     * @return
     */
    protected abstract BaseUser getUser(HttpServletRequest request);

    /**
     * 验证通过
     * @param request
     * @param response
     */
    protected  void onLogin( HttpServletRequest request,HttpServletResponse response,BaseUser user){
        UserContext.setUser(user);
    }

    /**
     * 登录验证失败
     * @param request
     * @param response
     */
    protected void onNoLogin(HttpServletRequest request,HttpServletResponse response) throws IOException {
        response.sendRedirect(getLoginUri());
    }

    /**
     * 异常
     * @param request
     * @param response
     * @param e
     */
    protected void onException(HttpServletRequest request,HttpServletResponse response,Exception e){
        try {
            this.onNoLogin(request, response);
        } catch (Throwable throwable) {
            throw new RuntimeException(e);
        }
    }

    private void onFinal() {
        UserContext.release();
    }

    public String getLoginUri() {
        return "";
    }

    public String getExcludeUriStr() {
        return excludeUriStr;
    }

    public void setExcludeUriStr(String excludeUriStr) {
        this.excludeUriStr = excludeUriStr;
    }

    public List<String> getExcludeUri() {
        return excludeUri;
    }

    public void setExcludeUri(List<String> excludeUri) {
        this.excludeUri = excludeUri;
    }
}
